package com.hqd.ch03.v20.aop.framework.aspectj;

import com.hqd.ch03.v20.aop.AfterAdvice;
import com.hqd.ch03.v20.aopalliance.intercept.MethodInterceptor;
import com.hqd.ch03.v20.aopalliance.intercept.MethodInvocation;

import javax.annotation.Nullable;
import java.lang.reflect.Method;

public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
        implements MethodInterceptor, AfterAdvice {
    public AspectJAfterThrowingAdvice(AspectJExpressionPointcut pointcut, Method aspectJAdviceMethod, Object aspect) {
        super(pointcut, aspectJAdviceMethod, aspect);
    }

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return true;
    }

    @Nullable
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        } catch (Throwable ex) {
            if (shouldInvokeOnThrowing(ex)) {
                invokeAdviceMethod(mi.getMethod(), getJoinPointMatch(), null, ex);
            }
            throw ex;
        }
    }

    private boolean shouldInvokeOnThrowing(Throwable ex) {
        return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
    }
}
